﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls.Primitives;

namespace LinkShareWpf.Commands
{




    // Per utilizzare al meglio MVVM, utilizziamo le AttachedBehavior o AttachedBehavior
    // Queste tipologie di classi espongono un AttachedProperty e servono ad invocare un comando allo scatenarsi di un cambio di stato.   
    
    public class SelectionBehavior
    {

        // In generale ad elementi della UI che implementano l'interfaccia ICommandSource è possibile associare un Command.
        // Esempio: i Button di System.Windows.Control ereditano da ButtonBase, che implementa l'interfaccia
        // public abstract class ButtonBase : ContentControl, ICommandSource

        // Ciò non è vero per tutti i controlli. Come nel nostro caso, in cui adoperiamo la classe ComboBox che eredita da Selector che non implementa ICommandSource.
        // public abstract class Selector : ItemsControl

        // Dep.Prop.: Rappresenta una proprietà che può essere impostata tramite metodi quali applicazione di stili, associazione dati, animazione ed ereditarietà.
        // notificando la modifica a tutti i contrilli a cui è legata, aggiornando l'interfaccia
         
        // Una AttachedProperty è una DependencyProperty che possono essere agganciata a degli oggetti.
        // In particolare servono per agganciare i Command anche agli oggetti WPF che non supportano navitamente i Command.
     
        public static DependencyProperty SelectionChangedProperty =

                // Serve per definire e registrare un AttachedProperty
                DependencyProperty.RegisterAttached("SelectionChanged",   // Il nome della A.P. da registrare
                typeof(ICommand),                                         // La A.P. è associata ad un oggetto di tipo ICommand
                typeof(SelectionBehavior),                                // Il type del proprietario che sta registrando la A.P. , questa classe
                new UIPropertyMetadata(SelectionBehavior.SelectedItemChanged));

                // I metadata su WPF servono per descrivere in maniera più chiara il comportamento che una proprietà deve avere in determinate condizioni di utilizzo
                // PropertyMetadata serve in generale ad impostare alla Proprietà, un valore di default, una callback, una coercecallback ed un validatore                        
                // Nel nostro caso è necessario solamente impostare la callback e avendo a che fare con un componente della UI utilizziamo UIProperyMetadata

   

        // Registra/DeRegistra l'evento di SelectionChanged
        // target: è il ComboBox ma più in generale il Selector dove Attached property è applicata
        // castando l'oggetto Selector, in modo che lo possa riutilizzare...con combobox,listbox => Ereditano dalla classe base Selector
        // e: è il valore della Propery, come vediamo contiene sia il vecchio che il nuovo valore. Contiene il DelegateCommand
        // Registro l'evento mapppando con il metodo SelectionChanged
        

        // La chiamata di callback è un metodo statico che viene chiamato ogni qual volta il valore della proprietà cambia.
        // Il nuovo valore viene passato tramite EventArgs,
        
        private static void SelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            Selector element = target as Selector;
            if (element == null) throw new InvalidOperationException("This behavior can be attached to Selector item only.");
           
            // Solo la prima volta il vecchio valore sara null
            
            if ((e.NewValue != null) && (e.OldValue == null))
            {
                element.SelectionChanged += SelectionChanged;
                // Adesso al cambio di Selezione abbiamo aggiunto un EventHandler ovvero SelectionChanged
                
            }
            else if ((e.NewValue == null) && (e.OldValue != null))
            {
                element.SelectionChanged -= SelectionChanged;
            }
        }

       
        private static void SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            UIElement element = (UIElement)sender; // Oggetto al quale è stata applicata l'AttachedProperty
            // .GetValue mi fa recuperare il valore associato a quella particolare AttachedProperty, che rappresenta il comando che voglio associare
            ICommand command = (ICommand)element.GetValue(SelectionBehavior.SelectionChangedProperty);
            // Recuperato il valore dell'AttachedProperty, che rappresenta il comando
            // e su questo invoco il metodo Execute, che esegue il comando
            command.Execute(element);
            // Definita l'AttachedProperty, rappresenta un legame tra il cambio di elemento selezionato ed il comando associato
        }












        // E' normale, WPF non usa le CLR properties, quelle vengono aggiunte per poter essere invocate da codice
        // Per settare la A.P. tramite Codice
        public static void SetSelectionChanged(DependencyObject target, ICommand value)
        {
            target.SetValue(SelectionBehavior.SelectionChangedProperty, value);
        }

    }
}







